package com.benjaminwan.read.free.utils

import com.benjaminwan.read.free.model.action.*
import com.benjaminwan.read.free.model.enums.Horizontal
import com.benjaminwan.read.free.model.enums.MouseButton
import com.benjaminwan.read.free.model.enums.Vertical
import com.benjaminwan.read.free.service.HidWrapperService
import com.orhanobut.logger.Logger
import kotlin.math.abs

object HIDUtils {
    fun sleep(delay: Long) {
        Logger.i("sleep:$delay")
        try {
            Thread.sleep(delay)
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    private fun keyboardKeyDown(hidWrapper: HidWrapperService?, action: KeyboardKeyDown) {
        hidWrapper?.keyboardKeyDown(action.key.toByte())
    }

    private fun keyboardKeyUp(hidWrapper: HidWrapperService?, action: KeyboardKeyUp) {
        hidWrapper?.keyboardKeyUp(action.key.toByte())
    }

    private fun mouseButtonDown(hidWrapper: HidWrapperService?, action: MouseButtonDown) {
        hidWrapper?.mouseButtonDown(action.which.ordinal)
    }

    private fun mouseButtonUp(hidWrapper: HidWrapperService?, action: MouseButtonUp) {
        hidWrapper?.mouseButtonUp(action.which.ordinal)
    }

    private fun mouseScroll(hidWrapper: HidWrapperService?, action: MouseScroll) {
        hidWrapper?.mouseScroll(action.delta.toByte())
    }

    private fun mouseMove(hidWrapper: HidWrapperService?, action: MouseMove) {
        hidWrapper?.mouseMove(action.dx, action.dy)
    }

    private fun keyBoardClick(hidWrapper: HidWrapperService?, action: KeyboardClick) {
        //Logger.i("keyBoardClick=${action.key}")
        hidWrapper?.keyboardKeyDown(action.key.toByte())
        sleep(action.delayRange.random().toLong())
        hidWrapper?.keyboardKeyUp(action.key.toByte())
    }

    private fun mouseButtonClick(hidWrapper: HidWrapperService?, action: MouseButtonClick) {
        //Logger.i("mouseButtonClick=${action.which}")
        hidWrapper?.mouseButtonDown(action.which.ordinal)
        sleep(action.delayRange.random().toLong())
        hidWrapper?.mouseButtonUp(action.which.ordinal)
    }

    fun mouseDrag(hidWrapper: HidWrapperService?, action: MouseDragPage, global: GlobalConfig) {
        val stepX = action.stepXRange ?: global.stepRange
        val stepY = action.stepYRange ?: global.stepRange
        mouseDrag(
            hidWrapper,
            action.xDirection, action.yDirection,
            action.dxRange, action.dyRange,
            stepX, stepY
        )
    }

    fun mouseDrag(
        hidWrapper: HidWrapperService?,
        xDirection: Horizontal, yDirection: Vertical,
        dxRange: IntRange, dyRange: IntRange,
        stepXRange: IntRange, stepYRange: IntRange
    ) {
        Logger.i("mouseDrag=$xDirection, $yDirection, $dxRange, $dyRange, $stepXRange, $stepYRange")
        val dx = if (xDirection == Horizontal.LEFT) dxRange.random() else -dxRange.random()
        val dy = if (yDirection == Vertical.UP) dyRange.random() else -dyRange.random()

        mouseMoveLong(hidWrapper, dx, dy, stepXRange, stepYRange, (1L..2))

        hidWrapper?.mouseButtonDown(MouseButton.Left.ordinal)

        sleep((4..6).random().toLong())

        mouseMoveLong(hidWrapper, -dx, -dy, stepXRange, stepYRange, (1L..2))

        sleep((4..6).random().toLong())

        hidWrapper?.mouseButtonUp(MouseButton.Left.ordinal)
    }

    private fun mouseMoveLong(
        hidWrapper: HidWrapperService?, action: MouseMoveLong, global: GlobalConfig
    ) {
        val stepX = action.stepXRange ?: global.stepRange
        val stepY = action.stepYRange ?: global.stepRange
        mouseMoveLong(hidWrapper, action.dx, action.dy, stepX, stepY, action.delayRange)
    }

    private fun mouseMoveLong(
        hidWrapper: HidWrapperService?,
        dx: Int, dy: Int,
        stepXRange: IntRange, stepYRange: IntRange, delayRange: LongRange
    ) {
        var dxMove = 0
        var dyMove = 0
        while (dxMove < abs(dx) || dyMove < abs(dy)) {
            val xStep = if (dxMove < abs(dx)) stepXRange.random() else 0
            val yStep = if (dyMove < abs(dy)) stepYRange.random() else 0

            val xStepFix = if ((abs(dx) - dxMove) > xStep) {
                xStep
            } else {
                abs(dx) - dxMove
            }

            val yStepFix = if ((abs(dy) - dyMove) > yStep) {
                yStep
            } else {
                abs(dy) - dyMove
            }

            val xSign = if (dx > 0) xStepFix else -xStepFix
            val ySign = if (dy > 0) yStepFix else -yStepFix

            hidWrapper?.mouseMove(xSign, ySign)
            dxMove += xStepFix
            dyMove += yStepFix
            Logger.i("xStep=$xStep,yStep=$yStep,xStepFix=$xStepFix,yStepFix=$yStepFix,xSign=$xSign,ySign=$ySign,dxMove=$dxMove,dyMove=$dyMove")
            sleep(delayRange.random())
        }
    }

    fun runAction(hidWrapper: HidWrapperService?, action: Action, global: GlobalConfig) {
        when (action) {
            //基本动作
            is Delay -> {
                //Logger.i("Delay(${idGroup}:$idAction)")
                val delay = if (action.delayRange == null) {
                    global.delayRange.random()
                } else {
                    action.delayRange.random()
                }
                sleep(delay)
            }
            is KeyboardKeyDown -> {
                //Logger.i("KeyboardKeyDown(${idGroup}:$idAction)")
                keyboardKeyDown(hidWrapper, action)
            }
            is KeyboardKeyUp -> {
                //Logger.i("KeyboardKeyUp(${idGroup}:$idAction)")
                keyboardKeyUp(hidWrapper, action)
            }
            is MouseButtonDown -> {
                //Logger.i("MouseButtonDown(${idGroup}:$idAction)")
                mouseButtonDown(hidWrapper, action)
            }
            is MouseButtonUp -> {
                //Logger.i("MouseButtonUp(${idGroup}:$idAction)")
                mouseButtonUp(hidWrapper, action)
            }
            is MouseScroll -> {
                //Logger.i("MouseButtonUp(${idGroup}:$idAction)")
                mouseScroll(hidWrapper, action)
            }
            is MouseMove -> {
                mouseMove(hidWrapper, action)
            }
            //组合动作
            is MouseDragPage -> {
                //Logger.i("MouseDragPage(${idGroup}:$idAction)")
                mouseDrag(hidWrapper, action, global)
            }
            is KeyboardClick -> {
                //Logger.i("KeyboardClick(${idGroup}:$idAction)")
                keyBoardClick(hidWrapper, action)
            }
            is MouseButtonClick -> {
                //Logger.i("KeyboardKeyUp(${idGroup}:$idAction)")
                mouseButtonClick(hidWrapper, action)
            }
            is MouseMoveLong -> {
                mouseMoveLong(hidWrapper, action, global)
            }
        }
    }
}